package array;

public class Matrix<T> {
	
	private T[][] elems;
	private int col;
	private int lin;
	
	public Matrix(int i, int j){
		col = i;
		lin = j;
		elems = (T[][]) new Object[i][j];
	}
	
	public Matrix(int i, int j, T init){
		col = i;
		lin = j;
		elems = (T[][]) new Object[i][j];
		for(int k = 0; k< i; k++){
			for(int p = 0; p < j; p++){
				elems[k][p] = init;
			}
		}
	}
	
	public T get(int i, int j) throws MatrixException{
		if((i <= col)&&(j <= lin)) return elems[i][j];
		else throw new MatrixException("ERRO:Indices invalidos!");
	}
	
	public boolean set(int i, int j, T elem) throws MatrixException{
		if((i <= col)&&(j <= lin)&&(elem != null)){
			elems[i][j] = elem;
			return true;
		}else throw new MatrixException("ERRO:Indices invalidos!");
	}
	
	public Matrix<T> sum(Matrix<T> m, Operator<T> op) throws MatrixException{
		Matrix M = new Matrix<T>(col, lin, null);
		if((lin== m.lin)&&(col == m.col)){
			for(int k = 0; k< lin; k++){
				for(int p = 0; p < col; p++){
					M.elems[k][p] = op.sum(m.elems[k][p],elems[k][p]);
				}
			}
		}else throw new MatrixException("ERRO:Indices invalidos!");
		return M;
	}
	
	public Matrix<T> mul(Matrix<T> m, Operator<T> op) throws MatrixException{
		Matrix M = new Matrix<T>(col, lin, null);
		if((lin == m.col)){
			for(int k = 0; k< lin; k++){
				for(int p = 0; p < m.col; p++){
					for(int l = 0;  l < m.col; l++)
					M.elems[k][p] =op.sum(op.mult(m.elems[k][l],elems[l][p]),(T)M.elems[k][p]);
				}
			}
		}else throw new MatrixException("ERRO:Indices invalidos!");
		return M;
	}
	
	public Matrix<T> prod(Operator<T> op, T elem){
		Matrix M = new Matrix<T>(col, lin, null);
		for(int k = 0; k< lin; k++){
			for(int p = 0; p < col; p++){
				M.elems[k][p] = op.prod(elems[k][p],elem);
			}
		}
		return M;
	}
	
	public int numLine(){
		return lin;
	}
	
	public int numCol(){
		return col;
	}
}
